/**
 * @class TypedEventEmitter
 * @description 事件派发器基类。
 */
export class TypedEventEmitter<T_Events extends Record<string | symbol, any>> {
  private _events: Map<keyof T_Events, ((...args: any[]) => void)[]>;
  constructor() {
    this._events = new Map();
  }
  /**
   * 监听一个事件。
   * @param eventName - 事件名称 (享受类型提示)
   * @param listener - 监听器函数 (参数享受类型提示)
   * @returns {this}
   */
  public on<K extends keyof T_Events>(eventName: K, listener: (payload: T_Events[K]) => void): this {
    if (!this._events.has(eventName)) {
      this._events.set(eventName, []);
    }
    const listeners = this._events.get(eventName)!;
    if (!listeners.includes(listener)) {
      listeners.push(listener);
    }

    return this;
  }

  /**
   * 添加一个只执行一次的监听器。
   * @param eventName - 事件名称 (享受类型提示)
   * @param listener - 监听器函数 (参数享受类型提示)
   * @returns {this}
   */
  public once<K extends keyof T_Events>(eventName: K, listener: (payload: T_Events[K]) => void): this {
    const onceWrapper = (payload: T_Events[K]) => {
      this.off(eventName, onceWrapper as any);
      listener(payload);
    };
    // 附加一个属性，方便在off()方法中识别和移除
    (onceWrapper as any).listener = listener;
    this.on(eventName, onceWrapper);
    return this;
  }

  /**
   * 移除一个事件监听器。
   * @param eventName - 事件名称
   * @param listener - 监听器函数
   * @returns {this}
   */
  public off<K extends keyof T_Events>(eventName: K, listener: (payload: T_Events[K]) => void): this {
    if (!this._events.has(eventName)) {
      return this;
    }
    const listeners = this._events.get(eventName)!;

    const originalListeners = listeners.filter((l) => l !== listener && (l as any).listener !== listener);

    if (originalListeners.length < listeners.length) {
      this._events.set(eventName, originalListeners as any);
    }

    return this;
  }

  /**
   * 移除指定事件的所有监听器，或移除所有事件的所有监听器。
   * @param eventName - (可选) 事件名称
   * @returns {this}
   */
  public removeAllListeners<K extends keyof T_Events>(eventName?: K): this {
    if (eventName) {
      this._events.delete(eventName);
    } else {
      this._events.clear();
    }
    return this;
  }

  /**
   * 按顺序同步执行每个监听器。
   * @param eventName - 事件名称 (享受类型提示)
   * @param payload - 传递给监听器的数据 (享受类型提示)
   * @returns {boolean} - 如果事件有监听器则返回true，否则返回false
   */
  public emit<K extends keyof T_Events>(eventName: K, payload: T_Events[K]): boolean {
    if (!this._events.has(eventName)) {
      return false;
    }
    // 创建一个监听器数组的副本，以防在emit期间监听器被修改
    const listeners = [...(this._events.get(eventName) || [])];
    for (const listener of listeners) {
      try {
        listener(payload as any);
      } catch (error) {
        console.error(`Error in event listener for ${String(eventName)}:`, error);
        // 如果定义了全局 error 事件，可以派发
        if (this._events.has("error" as any)) {
          this.emit("error" as any, error as any);
        }
      }
    }
    return true;
  }
}
